package school.community.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import school.community.dto.InfoDTO;
import school.community.dto.InfoQueryDTO;
import school.community.dto.PaginationDTO;
import school.community.dto.QuestionDTO;
import school.community.enums.NotificationTypeEnum;
import school.community.enums.SortEnum;
import school.community.exception.CustomizeErrorCode;
import school.community.exception.CustomizeException;
import school.community.mapper.*;
import school.community.model.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class InfoService {

  @Autowired
  private InfoMapper infoMapper;

  @Autowired
  private InfoExtMapper infoExtMapper;

  @Autowired
  private UserMapper userMapper;

  @Autowired
  private NotificationService notificationService;

  public PaginationDTO list(String search, String tag, String sort, Integer page, Integer size) {

    if (StringUtils.isNotBlank(search)) {
      String[] tags = StringUtils.split(search, " ");
      search = Arrays
              .stream(tags)
              .filter(StringUtils::isNotBlank)
              .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
              .filter(StringUtils::isNotBlank)
              .collect(Collectors.joining("|"));
    }

    PaginationDTO paginationDTO = new PaginationDTO();


    InfoQueryDTO infoQueryDTO = new InfoQueryDTO();
    infoQueryDTO.setSearch(search);
    if (StringUtils.isNotBlank(tag)) {
      tag = tag.replace("+", "").replace("*", "").replace("?", "");
      infoQueryDTO.setTag(tag);
    }

    for (SortEnum sortEnum : SortEnum.values()) {
      if (sortEnum.name().toLowerCase().equals(sort)) {
        infoQueryDTO.setSort(sort);

        if (sortEnum == SortEnum.HOT7) {
          infoQueryDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 7);
        }
        if (sortEnum == SortEnum.HOT30) {
          infoQueryDTO.setTime(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30);
        }
        break;
      }
    }
    infoQueryDTO.setState(1);

    //计算出总的记录的条数
    Integer totalCount = infoExtMapper.countBySearch(infoQueryDTO);

    //计算出总的活动的条数-如果本身就是请求的活动，那么上一步总的条数，则为总的活动的条数，无须计算，但是

    Integer totalPage;

    if (totalCount % size == 0) {
      totalPage = totalCount / size;
    } else {
      totalPage = totalCount / size + 1;
    }

    if (page < 1) {
      page = 1;
    }
    if (page > totalPage) {
      page = totalPage;
    }

    paginationDTO.setPagination(totalPage, page);
    Integer offset = page < 1 ? 0 : size * (page - 1);
    infoQueryDTO.setSize(size);
    infoQueryDTO.setPage(offset);
    List<Info> infos = infoExtMapper.selectBySearch(infoQueryDTO);
    List<InfoDTO> infoDTOList = new ArrayList<>();

    for (Info info : infos) {
      User user = userMapper.selectByPrimaryKey(info.getCreator());
      InfoDTO infoDTO = new InfoDTO();
      BeanUtils.copyProperties(info, infoDTO);
      infoDTO.setUser(user);
      infoDTOList.add(infoDTO);
    }

    paginationDTO.setData(infoDTOList);
    return paginationDTO;
  }

  public PaginationDTO list(Long userId, Integer page, Integer size) {
    PaginationDTO paginationDTO = new PaginationDTO();

    Integer totalPage;

    InfoExample infoExample = new InfoExample();
    infoExample.createCriteria()
            .andCreatorEqualTo(userId);
    Integer totalCount = (int) infoMapper.countByExample(infoExample);

    if (totalCount % size == 0) {
      totalPage = totalCount / size;
    } else {
      totalPage = totalCount / size + 1;
    }

    if (page < 1) {
      page = 1;
    }
    if (page > totalPage) {
      page = totalPage;
    }

    paginationDTO.setPagination(totalPage, page);

    //size*(page-1)
    Integer offset = size * (page - 1);
    InfoExample example = new InfoExample();
    example.createCriteria()
            .andCreatorEqualTo(userId);
    List<Info> infos = infoMapper.selectByExampleWithRowbounds(example, new RowBounds(offset, size));
    List<InfoDTO> infoDTOList = new ArrayList<>();

    for (Info info : infos) {
      User user = userMapper.selectByPrimaryKey(info.getCreator());
      InfoDTO infoDTO = new InfoDTO();
      BeanUtils.copyProperties(info, infoDTO);
      infoDTO.setUser(user);
      infoDTOList.add(infoDTO);
    }

    paginationDTO.setData(infoDTOList);
    return paginationDTO;
  }

  public InfoDTO getById(Long id) {
    Info info = infoMapper.selectByPrimaryKey(id);
    if (info == null) {
      throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
    }
    InfoDTO infoDTO = new InfoDTO();
    BeanUtils.copyProperties(info, infoDTO);
    User user = userMapper.selectByPrimaryKey(info.getCreator());
    infoDTO.setUser(user);
    return infoDTO;
  }

  public void createOrUpdate(Info info) {
    if (info.getId() == null) {
      // 创建
      info.setGmtCreate(System.currentTimeMillis());
      info.setGmtModified(info.getGmtCreate());
      info.setViewCount(0);
      info.setLikeCount(0);
      if (info.getTag().equals("公告")) {
        info.setCommentCount(1);
      } else {
        info.setCommentCount(0);
      }
      infoExtMapper.insertAndReturnId(info);
    } else {
      // 更新
      Info dbInfo = infoMapper.selectByPrimaryKey(info.getId());
      if (dbInfo == null) {
        throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
      }

      if (dbInfo.getCreator().longValue() != info.getCreator().longValue()) {
        throw new CustomizeException(CustomizeErrorCode.INVALID_OPERATION);
      }

      Info updateInfo = new Info();
      updateInfo.setGmtModified(System.currentTimeMillis());
      updateInfo.setTitle(info.getTitle());
      updateInfo.setDescription(info.getDescription());
      updateInfo.setTag(info.getTag());
      InfoExample example = new InfoExample();
      example.createCriteria()
              .andIdEqualTo(info.getId());
      int updated = infoMapper.updateByExampleSelective(updateInfo, example);
      if (updated != 1) {
        throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
      }
    }

    if (info.getTag().contains("活动")) {
      User user = userMapper.selectByPrimaryKey(info.getCreator());
      notificationService.createNotify(info.getCreator(),3L,user.getName(),info.getId(),info.getTitle(), NotificationTypeEnum.PUBLISH_ACTIVITY);
    }
  }

  /**
   * 更新活动的状态
   *
   * @param info
   */
  public void updataState(Info info) {
    // 更新
    Info dbInfo = infoMapper.selectByPrimaryKey(info.getId());
    if (dbInfo == null) {
      throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
    }

    Info updateInfo = new Info();
    updateInfo.setState(info.getState());

    InfoExample example = new InfoExample();
    example.createCriteria()
            .andIdEqualTo(info.getId());
    int updated = infoMapper.updateByExampleSelective(updateInfo, example);
    if (updated != 1) {
      throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
    }
  }

  public void incView(Long id) {
    Info info = new Info();
    info.setId(id);
    info.setViewCount(1);
    infoExtMapper.incView(info);
  }

  public List<InfoDTO> selectRelated(InfoDTO queryDTO) {
    if (StringUtils.isBlank(queryDTO.getTag())) {
      return new ArrayList<>();
    }
    String[] tags = StringUtils.split(queryDTO.getTag(), ",");
    String regexpTag = Arrays
            .stream(tags)
            .filter(StringUtils::isNotBlank)
            .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
            .filter(StringUtils::isNotBlank)
            .collect(Collectors.joining("|"));
    Info info = new Info();
    info.setId(queryDTO.getId());
    info.setTag(regexpTag);

    List<Info> infos = infoExtMapper.selectRelated(info);
    List<InfoDTO> infoDTOS = infos.stream().map(q -> {
     InfoDTO infoDTO = new InfoDTO();
      BeanUtils.copyProperties(q, infoDTO);
      return infoDTO;
    }).collect(Collectors.toList());
    return infoDTOS;
  }

  /**
   * 列举state=0的活动
   * @param page
   * @param size
   * @return
   */
  public PaginationDTO listByState(Integer page, Integer size) {
    PaginationDTO paginationDTO = new PaginationDTO();

    Integer totalPage;

    InfoQueryDTO infoQueryDTO = new InfoQueryDTO();
    //count tag="活动",state=0的信息
    Integer totalCount = (int) infoExtMapper.countByState(infoQueryDTO);
    if (totalCount % size == 0) {
      totalPage = totalCount / size;
    } else {
      totalPage = totalCount / size + 1;
    }

    if (page < 1) {
      page = 1;
    }
    if (page > totalPage) {
      page = totalPage;
    }

    //设置分页
    paginationDTO.setPagination(totalPage, page);
    Integer offset = page < 1 ? 0 : size * (page - 1);
    infoQueryDTO.setSize(size);
    infoQueryDTO.setPage(offset);

    //选择tag = "活动",state = 0的信息
    List<Info> infos = infoExtMapper.selectByState(infoQueryDTO);
    List<InfoDTO> infoDTOList = new ArrayList<>();

    for (Info info : infos) {
      User user = userMapper.selectByPrimaryKey(info.getCreator());
      InfoDTO infoDTO = new InfoDTO();
      BeanUtils.copyProperties(info, infoDTO);
      infoDTO.setUser(user);
      infoDTOList.add(infoDTO);
    }

    paginationDTO.setData(infoDTOList);
    return paginationDTO;
  }
}
